home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cpp_libs
/
tools
/
cie.lha
/
cie
/
goto-file.el
< prev
next >
Wrap
Lisp/Scheme
|
1993-06-21
|
6KB
|
148 lines
;;; goto-file.el
;;; By binding goto-file to a key or mouse stroke, you can essentially
;;; make filenames "hot"; it will attempt to find that file in the
;;; current buffer's default directory. If no such file exists, then
;;; it checks the current tags-table, gambling that it is one of your
;;; source files and will be tagged.
;;;
;;; Furthermore, it will try to go to the right location in the file.
;;; If there is an adjacent line number, then it will go to that line.
;;; Or if there is an adjacent grep pattern, then it will find that pattern.
;;;
;;; For instance, if you are in a shell and do an "ls", you can then click on
;;; any file name to open the file. If you do a "make", you can click on any
;;; error msg to take you to the line of the error. If you are in dbx, and it
;;; outputs a break or an assert outputs file/line, then you can simply click
;;; on the filename to take you to the line. If you do a "grep", then you
;;; can simply click on the filename of the match that you want to go to.
;;; IMO, this is preferable to M-x compile or grep, because there is no need
;;; to proceed in order. It also works everywhere: in source files, in
;;; shells, in night build logs, in mail buffers, etc.
;;; Copyright (C) 1993, Intellection Inc.
;;;
;;; Author: Brian M Kennedy (kennedy@intellection.com)
;;;
;;; This program is free software; you can redistribute it and/or modify
;;; it under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 1, or (at your option)
;;; any later version.
;;;
;;; This program is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; A copy of the GNU General Public License can be obtained from the
;;; Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;;; 92/07/23 Brian M Kennedy Original
(provide 'goto-file)
(require 'tags)
(defvar goto-file-chars "-A-Za-z./_=+~#0-9"
"Characters that goto-file considers part of a filename.
Intentionally does not include (by default) ,:<> and quotes because
these are more often delimiters than part of the filename.")
(defvar goto-file-other-window-p t
"When non-nil, goto new file in other window.")
(defun goto-file (&optional dont-use-tags-p)
"Attempts to identify a filename at or around point. If it finds one,
then it attempts to find a line number of the form 'line nn' on the
same line as the filename. If there is no line number, then it checks
if the filename was followed by a colon. If so, it assumes it is a
grep-style pattern that was matched in the file.
It then tries to find a file by that filename in the current-dirctory.
If there is none and the optional argument is nil, then it attempts to
identify a file that has been tagged with the same name in order to get a
full pathname.
If it finds a file (either way), then it opens it in another window.
If there was line number information, then it will goto that line.
If not, and there was a grep-style pattern, then it searches for that
pattern in the file (and sets it up so that you can search for additional
matches via incremental search)."
(interactive "P")
(let ((filename nil)
(basename nil)
(file nil)
(line nil)
(pattern nil))
(save-excursion
;; Get filename
(skip-chars-backward goto-file-chars)
(let (start-point base-point end-point)
(setq start-point (point))
(skip-chars-forward "./~") ;; strip leading context info for tagfile lookup
(setq base-point (point))
(skip-chars-forward goto-file-chars)
(setq end-point (point))
(setq filename (buffer-substring start-point end-point))
(setq basename (buffer-substring base-point end-point)) )
;; Get pattern
(if (looking-at ":")
(progn (forward-char 1)
(setq pattern (buffer-substring (point)
(progn (end-of-line) (point)))) ))
;; Get line
(cond ((looking-at "([0-9]+")
(forward-char 1)
(setq line (string-to-int
(buffer-substring (point)
(progn (skip-chars-forward "0-9")
(point) )))) )
((looking-at ".*line [0-9]")
(re-search-forward ".*line ")
(setq line (string-to-int
(buffer-substring (point)
(progn (skip-chars-forward "0-9")
(point) )))) )
((re-search-backward "line [0-9]"
(save-excursion (beginning-of-line) (point))
t)
(forward-char 5)
(setq line (string-to-int
(buffer-substring (point)
(progn (skip-chars-forward "0-9")
(point) )))) )
))
;; Goto the file
(if filename
(let ((fullname (expand-file-name filename)))
(if (and (not dont-use-tags-p)
(not (and fullname (file-exists-p fullname))))
(setq fullname (expand-tagged-file-name basename)))
(if (and fullname (file-exists-p fullname))
(progn
(if goto-file-other-window-p
(find-file-other-window fullname)
(find-file fullname))
(cond (line (goto-line line))
(pattern (setq search-last-string pattern)
(goto-char (point-min))
(search-forward pattern nil t) )
))
(if dont-use-tags-p
(error "No file named %s is in current directory." filename)
(error "No file named %s is in current or tagged directories." filename)
) ))
(error "No filename found at point.") )))
(defun expand-tagged-file-name (filename)
"Find a tagged file with a name that includes 'filename' in it.
If one is found, return that file's expanded filename.
Otherwise, return nil."
;; Find the tagged file
(save-excursion
(visit-tags-table-buffer)
(beginning-of-buffer)
(if (re-search-forward (concat "\f\n\\(.*/\\)?" filename ",") nil t)
(expand-file-name (file-of-tag) (file-name-directory tags-file-name)) )))